/************************************************************************
                                                                     
   Xceed Ultimate ListBox for Silverlight                                                                                                                                            
   Copyright (C) 2010 Xceed Software Inc.    
                                                                     
   This program is provided to you under the terms of the GNU General Public  
   License version 2 as published by the Free Software Foundation. 
        
   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY, without even the implied warranty of 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License along 
   with this program, if not, write to the Free Software Foundation, Inc., 
   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

   This program can be provided to you by Xceed Software Inc. under a
   proprietary commercial license agreement for use in non-Open Source
   projects. Visit Xceed.com to find the commercial edition of 
   Xceed Ultimate ListBox for Silverlight.                                    
                                                                      
 **********************************************************************/

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.Collections.Generic;

namespace Xceed.Silverlight.ListBox
{
  public class HierarchicalGroupValueControl : ItemsControl
  {
    #region Constructor
    public HierarchicalGroupValueControl()
    {
      this.DefaultStyleKey = typeof( HierarchicalGroupValueControl );
      this.SeparatorVisibility = Visibility.Visible;
    }
    #endregion

    #region ItemContainerStyle Property

    public static readonly DependencyProperty ItemContainerStyleProperty = DependencyProperty.Register(
      "ItemContainerStyle",
      typeof( Style ),
      typeof( HierarchicalGroupValueControl ),
      new PropertyMetadata( ( Style )null ) );

    public Style ItemContainerStyle
    {
      get
      {
        return ( Style )this.GetValue( HierarchicalGroupValueControl.ItemContainerStyleProperty );
      }
      set
      {
        this.SetValue( HierarchicalGroupValueControl.ItemContainerStyleProperty, value );
      }
    }

    #endregion

    #region GroupValueDataTemplates Property

    public static readonly DependencyProperty GroupValueDataTemplatesProperty = DependencyProperty.Register(
      "GroupValueDataTemplates",
      typeof( List<GroupValueDataTemplate> ),
      typeof( HierarchicalGroupValueControl ),
      new PropertyMetadata( ( List<GroupValueDataTemplate> )null ) );

    public List<GroupValueDataTemplate> GroupValueDataTemplates
    {
      get
      {
        return ( List<GroupValueDataTemplate> )this.GetValue( HierarchicalGroupValueControl.GroupValueDataTemplatesProperty );
      }
      set
      {
        this.SetValue( HierarchicalGroupValueControl.GroupValueDataTemplatesProperty, value );
      }
    }

    #endregion

    #region ParentHierarchicalGroupValueControl Attached Property

    public static readonly DependencyProperty ParentHierarchicalGroupValueControlProperty = DependencyProperty.RegisterAttached(
      "ParentHierarchicalGroupValueControl",
      typeof( HierarchicalGroupValueControl ),
      typeof( HierarchicalGroupValueControl ),
      new PropertyMetadata( ( HierarchicalGroupValueControl )null ) );

    public static HierarchicalGroupValueControl GetParentHierarchicalGroupValueControl( DependencyObject obj )
    {
      return ( HierarchicalGroupValueControl )obj.GetValue( HierarchicalGroupValueControl.ParentHierarchicalGroupValueControlProperty );
    }

    public static void SetParentHierarchicalGroupValueControl( DependencyObject obj, HierarchicalGroupValueControl value )
    {
      obj.SetValue( HierarchicalGroupValueControl.ParentHierarchicalGroupValueControlProperty, value );
    }

    #endregion


    #region SeparatorVisibility Property
    public Visibility SeparatorVisibility
    {
      get;
      set;
    }
    #endregion

    #region Protected Methods
    protected override DependencyObject GetContainerForItemOverride()
    {
      return new HierarchicalGroupValueItem();
    }

    protected override void PrepareContainerForItemOverride( DependencyObject element, object item )
    {
      base.PrepareContainerForItemOverride( element, item );
      HierarchicalGroupValueItem container = element as HierarchicalGroupValueItem;
      FieldNameValuePair fieldNameValuePair = item as FieldNameValuePair;

      if( container == null )
        throw new ListBoxInternalException( "container isn't a HierarchicalGroupValueItem." );

      if( fieldNameValuePair == null )
        throw new ListBoxInternalException( "item isn't a FieldNameValuePair" );

      DataTemplate contentTemplate = null;

      // Get the content template associated to the object we want to display.
      if( this.GroupValueDataTemplates != null )
      {
        // Look for a DataTemplate for the field name
        contentTemplate = m_dataTemplateSelector.Select( fieldNameValuePair.FieldName, this.GroupValueDataTemplates );

        if( contentTemplate == null )
          contentTemplate = this.ItemTemplate;

        if( contentTemplate != null )
        {
          container.ContentTemplate = contentTemplate;
        }
        else
        {
          container.ClearValue( HierarchicalGroupValueItem.ContentTemplateProperty );
        }
      }

      // Sets the container style if a style has been specified
      // on the group configuration.
      if( this.ItemContainerStyle != null )
      {
        container.Style = this.ItemContainerStyle;
      }
      else
      {
        container.ClearValue( HierarchicalGroupValueItem.StyleProperty );
      }

      // The data context of the container is the GroupValue. We don't want
      // the pair (groupValue / fieldName) to be the DataContext. This pair
      // is only used to get the Content template with the selector.
      container.DataContext = fieldNameValuePair.Value;

      // Setting IsRoot and IsLeaf property on the container
      container.IsRoot = fieldNameValuePair.IsRoot;
      container.IsLeaf = fieldNameValuePair.IsLeaf;

      HierarchicalGroupValueControl.SetParentHierarchicalGroupValueControl( container, this );

    }

    protected override void ClearContainerForItemOverride( DependencyObject element, object item )
    {
      base.ClearContainerForItemOverride( element, item );

      HierarchicalGroupValueItem container = element as HierarchicalGroupValueItem;

      if( container != null )
      {
        container.ClearValue( HierarchicalGroupValueControl.ParentHierarchicalGroupValueControlProperty );
      }
    }

    #endregion

    #region Private Members

    HierarchicalContentTemplateSelector m_dataTemplateSelector = new HierarchicalContentTemplateSelector();

    #endregion

    #region Nested Classes

    private class HierarchicalContentTemplateSelector
    {
      #region Constructor
      internal HierarchicalContentTemplateSelector()
      {

      }
      #endregion

      internal DataTemplate Select( string fieldName, List<GroupValueDataTemplate> groupValueDataTemplates )
      {
        // Look for the field name across the group value DataTemplate
        foreach( GroupValueDataTemplate groupValueDataTemplate in groupValueDataTemplates )
        {
          if( groupValueDataTemplate.FieldNames.Contains( fieldName ) )
            return groupValueDataTemplate.Template;
        }

        return null;

      }

    }


    #endregion

  }
}
